#include <string.h>

///************************************************************************/
/// StringSpan and string operations
///************************************************************************/

struct StringSpan
{
	const char* str;
	size_t len;
};

typedef struct StringSpan StringSpan;
typedef const char* str;
#define true 1
#define false 0

void SSPrint(StringSpan span);
StringSpan SSMake(const char* start, const char* end);
void SSSet(StringSpan* span, const char* text);
int SSCmp(StringSpan* span1, StringSpan* span2);
int SSCmpStr(StringSpan* span1, str text);
void SSStart(StringSpan* span, str start);
void SSStop(StringSpan* span, str end);

str SwallowWhitespace(str text);
str GetWord(StringSpan* ss, str text);

///************************************************************************/
/// Matching
///************************************************************************/

enum MatchType
{
	MATCH_LITERAL, /// '...'
	MATCH_LINK, /// word, float, int, etc...
	MATCH_GROUP, /// ()
	MATCH_ALT_GROUP, /// []

	MATCH_BUILTIN,
};

enum Multiples
{
	ML_OPTION, /// ?
	ML_PLUS, /// +
	ML_STAR, /// *
};

typedef struct
{
	int IgnoreWhitespace;
	va_list OutList;
} MatchOptions;

typedef struct MatchItem MatchItem;

///************************************************************************/
/// MatchItem methods
///************************************************************************/

/// Matches the string provided against a MatchItem, with MatchOptions
/// Arguments:
/// - the MatchItem against which the match is made
/// - the MatchOptions object
/// - the string that we're supposed to match
/// Return:
/// Pointer after the matched text
typedef str(*MatchFunction)(MatchItem*, MatchOptions*, str);

/// Parses the provided string span and converts it to a type, and outputs it
/// into the next vararg at MatchOptions::OutList.
/// Arguments:
/// - the MatchItem we are parsing
/// - the matched text
/// - the output name provided by the user
/// - the MatchOptions object
typedef void(*ParseFunction)(MatchItem*, StringSpan, StringSpan, MatchOptions*);

/// Call this function at the beginning of using the REScan library.
void StartREScan(void);

void DestroyItem(MatchItem* item);
void AppendChild(MatchItem* item, MatchItem* child);

str MatchGroup(MatchItem* item, MatchOptions* opts, str text);

///************************************************************************/
/// Links
///************************************************************************/

void AddLink(StringSpan name, MatchItem* item);
MatchItem* GetLink(StringSpan* name);

///************************************************************************/
/// Parsing
///************************************************************************/

str ParseGroup(MatchItem** it, str text);
str Scan(str in, str format, ...);
